package com.bowlong.tool;

import java.awt.Color;
import java.awt.Point;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Queue;
import java.util.Random;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.UUID;
import java.util.Vector;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import com.alibaba.fastjson.JSON;
import com.bowlong.io.ByteInStream;
import com.bowlong.io.ByteOutStream;
import com.bowlong.io.FileEx;
import com.bowlong.lang.MyThreadFactory;
import com.bowlong.lang.NumEx;
import com.bowlong.lang.RndEx;
import com.bowlong.lang.StrEx;
import com.bowlong.lang.timeout.ConcurrentTimeoutMap;
import com.bowlong.lang.timeout.TimeoutMap;
import com.bowlong.objpool.ByteInPool;
import com.bowlong.objpool.ByteOutPool;
import com.bowlong.objpool.StringBufPool;
import com.bowlong.pinyin.PinYin;
import com.bowlong.text.Encoding;
import com.bowlong.util.BidiMap;
import com.bowlong.util.DateEx;
import com.bowlong.util.ListEx;
import com.bowlong.util.MapEx;
import com.bowlong.util.MultiKey2;
import com.bowlong.util.NewList;
import com.bowlong.util.NewMap;
import com.bowlong.util.NewSet;
import com.bowlong.util.StrBuilder;

@SuppressWarnings({ "unchecked", "rawtypes" })
public class Lib2 {
	public static final <E> Set<E> newCopyOnWriteSet() {
		return new java.util.concurrent.CopyOnWriteArraySet<E>();
	}

	public static final <K, V> BidiMap<K, V> newBidiMap() {
		return new BidiMap<K, V>();
	}

	public static final <E> List<E> toList(Set<E> m) {
		return new ArrayList(m);
	}

	public static final List listIt(Object... var) {
		List result = new Vector();
		for (Object e : var) {
			result.add(e);
		}
		return result;
	}

	public static int sum(List<Integer> list) {
		int r2 = 0;
		for (int i : list)
			r2 += i;
		return r2;
	}

	public static int sum(int... args) {
		int r2 = 0;
		for (int i : args)
			r2 += i;
		return r2;
	}

	public static int[] arr(int... o) {
		return o;
	}

	public static boolean in(List vars, int i) {
		if (vars.contains(i))
			return true;
		return false;
	}

	public static boolean in(Set vars, int[] arr) {
		for (int i : arr) {
			if (vars.contains(i))
				return true;
		}
		return false;
	}

	public static boolean in(int[] arr, Set<Integer> vars) {
		Iterator<Integer> it = vars.iterator();
		while (it.hasNext()) {
			int i = it.next();
			if (in(arr, i))
				return true;
		}
		return false;
	}

	public static final boolean intersectedPoints(List<Point> list, Point p) {
		if (list == null || list.isEmpty() || p == null)
			return false;

		Set<String> c = new HashSet<String>();
		for (Point p1 : list) {
			c.add(p1.toString());
		}
		return c.contains(p.toString());
	}

	public static final int max(List<Integer> list) {
		return Collections.max(list);
	}

	public static final int min(List<Integer> list) {
		return Collections.min(list);
	}

	public static final String nextPassword() {
		int v = 100000 + nextInt(800000);
		return String.valueOf(v);
	}

	public static final List<Map> sortMap(List m1, final String key) {
		Collections.sort(m1, new Comparator<Map>() {
			public int compare(Map o1, Map o2) {
				Object v1 = o1.get(key);
				Object v2 = o2.get(key);
				if (v1 == null || v2 == null)
					return 0;
				return compareTo(v1, v2);
			}
		});
		return m1;
	}

	public static final <E> List<E> sortMap(List<E> list,
			Comparator<E> comparator) {
		Collections.sort(list, comparator);
		return list;
	}

	// ///////////////////////////////////////////////////
	public static final byte[] readFully(String fn) throws IOException {
		File f = new File(fn);
		return readFully(f);
	}

	public static final void writeFully(String fn, byte[] b) throws IOException {
		File f = new File(fn);
		writeFully(f, b);
	}

	// ///////////////////////////////////////////////////

	public static final SimpleDateFormat sdf(String fmt) {
		return new SimpleDateFormat(fmt);
	}

	public static final Date parse(String fmt, String s) {
		try {
			SimpleDateFormat f = sdf(fmt);
			return f.parse(s);
		} catch (Exception e) {
		}
		return new Date();
	}

	public static final String format(Date dat, String fmt) {
		return sdf(fmt).format(dat);
	}
	

	public static int day() {
		return DateEx.day();
	}

	public static final int yearMMdd(Date dat) {
		String val = new SimpleDateFormat("yyyyMMdd").format(dat);
		return NumEx.stringToInt(val);
	}

	public static final int yearMMddHH(Date dat) {
		String val = new SimpleDateFormat("yyyyMMddHH").format(dat);
		return NumEx.stringToInt(val);
	}

	public static int year(Date dat) {
		return DateEx.year(dat);
	}

	public static int month(Date dat) {
		return DateEx.month(dat);
	}

	public static int day(Date dat) {
		return DateEx.day(dat);
	}

	public static int hour(Date dat) {
		return DateEx.hour(dat);
	}

	public static int minute(Date dat) {
		return DateEx.minute(dat);
	}

	public static int second(Date dat) {
		return DateEx.second(dat);
	}

	public static final String nowYearMMddHHmmss() {
		return format(new Date(), fmt_yyyy_MM_dd_HH_mm_ss);
	}

	public static final String tFmt(Date dat) {
		return format(dat, fmt_yyyy_MM_dd_HH_mm_ss);
	}

	public static final String tFmt2(Date dat) {
		return format(dat, "yyyy/MM/dd HH:mm:ss");
	}

	public static final String tFmtYyyyMmDd() {
		return format(new Date(), fmtYyyyMmDd);
	}

	public static final String nowHourMm() {
		return format(new Date(), fmt_HH_mm);
	}

	public static final String nowMonthDdHHmm() {
		return format(new Date(), fmt_MM_dd_HH_mm);
	}

	// 时间2 减去时间 1 时间差
	public static final long tick(Date begin, Date end) {
		long l1 = begin.getTime();
		long l2 = end.getTime();
		return l2 - l1;
	}

	public static final long tick(long begin, Date end) {
		long l1 = begin;
		long l2 = end.getTime();
		return l2 - l1;
	}

	public static final long tick(Date begin, long end) {
		long l1 = begin.getTime();
		long l2 = end;
		return l2 - l1;
	}

	public static final long tick(long begin, long end) {
		long l1 = begin;
		long l2 = end;
		return l2 - l1;
	}

	public static final String DEC_FMT_1 = "###,###.000";
	public static final String DEC_FMT_2 = "#0.000%";
	public static final String DEC_FMT_3 = ".00";

	public static final String format(double number, String fmt) {
		return new DecimalFormat(fmt).format(number);
	}

	public static final String format(float number, String fmt) {
		return new DecimalFormat(fmt).format(number);
	}

	public static final String fixNInt(final int v, final int n) {
		return String.format("%0" + n + "d", v);
	}

	// ///////////////////////////////////////////////////
	public final static int distance(Point a, Point b) {
		int x1 = a.x;
		int y1 = a.y;
		int x2 = b.x;
		int y2 = b.y;
		return distance(x1, y1, x2, y2);
	}

	public final static int distance90Angle(Point a, Point b) {
		int x1 = a.x;
		int y1 = a.y;
		int x2 = b.x;
		int y2 = b.y;
		return Math.abs(x2 - x1) + Math.abs(y2 - y1);
	}

	public final static int distance90Angle(int x1, int y1, int x2, int y2) {
		return Math.abs(x2 - x1) + Math.abs(y2 - y1);
	}

	// ///////////////////////////////////////////////////
	public final static int distanceXy(int x1, int y1, int x2, int y2) {
		double v = Math.abs(x1 - x2) + Math.abs(y1 - y2);
		return (int) v;
	}

	public final static List<Point> point4(final Point f, final Point t) {
		List<Point> p4 = new ArrayList<Point>();
		p4.add(new Point(t.x - 1, t.y));
		p4.add(new Point(t.x + 1, t.y));
		p4.add(new Point(t.x, t.y - 1));
		p4.add(new Point(t.x, t.y + 1));
		Collections.sort(p4, new Comparator<Point>() {
			@Override
			public int compare(Point o1, Point o2) {
				Integer d1 = distance90Angle(f, o1);
				Integer d2 = distance90Angle(f, o2);
				return d1.compareTo(d2);
			}
		});
		return p4;
	}

	public final static Point near(List<Point> p4) {
		return p4.get(1);
	}

	public final static Point far(List<Point> p4) {
		return p4.get(p4.size() - 1);
	}

	public final static Point p2(final Point f, final Point t, final int d) {
		int x2 = f.x;
		int y2 = f.y;

		int dist = distance90Angle(f, t);
		if (dist < d)
			return new Point(t.x, t.y);

		int d2 = d;
		int mx = Math.abs(t.x - f.x);
		int my = Math.abs(t.y - f.y);

		if (mx > my) {
			if (d2 > 0) {
				if (f.x > t.x)
					x2 = d2 > mx ? f.x - mx : f.x - d2;
				else
					x2 = d2 > mx ? f.x + mx : f.x + d2;
				d2 -= mx;
			}

			if (d2 > 0) {
				if (f.y > t.x)
					y2 = d2 > my ? f.y - my : f.y - d2;
				else
					y2 = d2 > my ? f.y + my : f.y + d2;
				d2 -= my;
			}
		} else {
			if (d2 > 0) {
				if (f.y > t.y) {
					y2 = d2 > my ? f.y - my : f.y - d2;
				} else {
					y2 = d2 > my ? f.y + my : f.y + d2;
				}
				d2 -= d2 > my ? my : d2;
			}

			if (d2 > 0) {
				if (f.x > t.x)
					x2 = d2 > mx ? f.x - mx : f.x - d2;
				else
					x2 = d2 > mx ? f.x + mx : f.x + d2;
				d2 -= d2 > mx ? mx : d2;
			}
		}

		Point p = new Point(x2, y2);
		return p;
	}

	public final static Point move2d(final Point f, final Point t, final int d,
			final int range, List<Point> occupys) {
		if (f == null || t == null)
			return null;
		if (occupys == null)
			occupys = new ArrayList<Point>();

		List<Point> p4 = point4(f, t);

		Iterator<Point> it = p4.iterator();
		while (it.hasNext()) {
			int dist = distance90Angle(f, it.next());
			if (dist > d)
				it.remove();
		}

		if (p4.isEmpty()) {
			p4.add(p2(f, t, d));
		}

		if (occupys.isEmpty())
			return p4.get(0);

		for (Point p : occupys) {
			if (intersectedPoints(occupys, p)) {
				continue;
			}
			return p;
		}

		return move2d(f, t, d - 1, range, occupys);
	}

	public final static List<Point> points2(int x1, int y1, int x2, int y2) {
		List<Point> result = newList();
		Point a = new Point(x1, y1);
		Point b = new Point(x2, y2);
		if (x1 > x2) {
			Point x = a;
			a = b;
			b = x;
		}
		Set<String> e = newSet();
		for (int i = a.x + 1; i < b.x; i++) {
			double k = ((double) (a.y - b.y)) / (a.x - b.x);
			double y = k * (i - a.x) + a.y;
			// double d = y - (int) y;
			int ey = (int) y;
			String key = i + "," + ey;
			if (e.contains(key))
				continue;
			e.add(key);
			result.add(new Point(i, ey));
		}
		return result;
	}

	public static boolean isEmpty(Queue o) {
		return o == null || o.isEmpty();
	}

	public static boolean notNull(Object o) {
		return o != null;
	}

	public static boolean notEmpty(byte[] o) {
		return o != null && o.length > 0;
	}

	public static boolean notEmpty(List o) {
		return o != null && !o.isEmpty();
	}

	public static boolean notEmpty(Map o) {
		return o != null && !o.isEmpty();
	}

	public static boolean notEmpty(Queue o) {
		return o != null && !o.isEmpty();
	}

	public static boolean notEmpty(String o) {
		return o != null && !o.isEmpty();
	}

	public static String e2s(Throwable e) {
		return e2s(e, null, new Object[0]);
	}

	public static String e2s(Throwable e, Object obj) {
		return e2s(e, String.valueOf(obj), new Object[0]);
	}

	public static String e2s(Throwable e, String fmt, Object... args) {
		StringBuffer sb = StringBufPool.borrowObject();
		try {
			sb.append(e);
			if (fmt != null && !fmt.isEmpty() && args.length <= 0)
				sb.append(" - ").append(fmt);
			if (fmt != null && !fmt.isEmpty() && args.length > 0) {
				String str = StrBuilder.builder().ap(fmt, args).str();
				sb.append(" - ").append(str);
			}
			sb.append("\r\n");
			for (StackTraceElement ste : e.getStackTrace()) {
				sb.append("at ");
				sb.append(ste);
				sb.append("\r\n");
			}
			return sb.toString();
		} finally {
			StringBufPool.returnObject(sb);
		}
	}

	public static final ScheduledExecutorService newScheduledThreadPool(
			String name, int n) {
		return Executors.newScheduledThreadPool(n, new MyThreadFactory(name,
				false));
	}

	public static final ScheduledExecutorService newThreadPool(int num) {
		return Executors.newScheduledThreadPool(num);
	}

	public static final void execute(ExecutorService ses, Runnable r) {
		ses.execute(r);
	}

	public static final ScheduledFuture<?> scheduledFixedRate(
			ScheduledExecutorService ses, Runnable r, long initialDelay,
			long delay) {
		return ses.scheduleAtFixedRate(r, initialDelay, delay,
				TimeUnit.MILLISECONDS);
	}

	public static final ScheduledFuture<?> schedule(
			ScheduledExecutorService ses, final Runnable r, final Date d) {
		long delay = d.getTime() - now();
		delay = delay <= 0 ? 1 : delay;
		return ses.schedule(r, delay, TimeUnit.MILLISECONDS);
	}

	// //////////////////////////////////////////////
	public static final String pinyin(String s) {
		return PinYin.pinYin(s);
	}

	public static final String py(String s) {
		return PinYin.shortPinYin(s);
	}

	// //////////////////////////////////////////////
	public static String reword(String s) {
		while (s.indexOf("[") >= 0) {
			s = s.replace("[", "(");
		}

		while (s.indexOf("]") >= 0) {
			s = s.replace("]", ")");
		}
		return s;
	}


	public static final String tmStr(long ms) {
		int ss = 1000;
		int mi = ss * 60;
		int hh = mi * 60;

		long hour = (ms) / hh;
		long minute = (ms - hour * hh) / mi;
		long second = (ms - hour * hh - minute * mi) / ss;

		StringBuffer sb = StringBufPool.borrowObject();
		try {
			if (hour > 0) {
				if (hour < 10)
					sb.append("0");
				sb.append(hour);
				sb.append(":");
			}
			if (minute > 0) {
				if (minute < 10)
					sb.append("0");
				sb.append(minute);
				sb.append(":");
			}
			if (second < 10)
				sb.append("0");
			sb.append(second).append("s");
			return sb.toString();
		} finally {
			StringBufPool.returnObject(sb);
		}
	}

	public static List many(Object o) {
		List ret = newList();
		ret.add(o);
		return ret;
	}

	public static <T> T single(List o) {
		if (o == null || o.isEmpty())
			return null;
		return (T) o.get(0);
	}

	public static final int interval(int v, int min, int max) {
		v = v < min ? min : v;
		v = v > max ? max : v;
		return v;
	}

	public static String nStr(long n) {
		if (n < -1000000)
			return ((int) (n / 1000000)) + "M";
		if (n < -10000)
			return ((int) (n / 10000)) + "W";
		if (n < -1000)
			return ((int) (n / 1000)) + "K";
		if (n < 0)
			return "" + n;
		else if (n < 1000)
			return "" + n;
		else if (n < 10000)
			return ((int) (n / 1000)) + "K";
		else if (n < 1000000)
			return ((int) (n / 10000)) + "W";
		else
			return ((int) (n / 1000000)) + "M";
	}

	public static boolean eq(boolean v1, boolean v2) {
		return v1 == v2;
	}

	public static boolean eq(byte v1, byte v2) {
		return v1 == v2;
	}

	public static boolean eq(short v1, short v2) {
		return v1 == v2;
	}

	public static boolean eq(int v1, int v2) {
		return v1 == v2;
	}

	public static boolean eq(long v1, long v2) {
		return v1 == v2;
	}

	public static boolean eq(float v1, float v2) {
		return v1 == v2;
	}

	public static boolean eq(double v1, double v2) {
		return v1 == v2;
	}

	public static boolean eq(String v1, String v2) {
		return v1.equals(v2);
	}

	public static boolean eqYear(Date v1, Date v2) {
		return year(v1) == year(v2);
	}

	public static boolean eqMonth(Date v1, Date v2) {
		return month(v1) == month(v2);
	}

	public static boolean eqDay(Date v1, Date v2) {
		return day(v1) == day(v2);
	}

	public static boolean eqYearMonthDay(Date v1, Date v2) {
		return eqYear(v1, v2) && eqMonth(v1, v2) && eqDay(v1, v2);
	}

	public static boolean eqHour(Date v1, Date v2) {
		return hour(v1) == hour(v2);
	}

	public static boolean eqMinute(Date v1, Date v2) {
		return minute(v1) == minute(v2);
	}

	public static boolean eqSecond(Date v1, Date v2) {
		return second(v1) == second(v2);
	}

	public static void writeText(File fn, String str) {
		Charset charset = Encoding.UTF8;
		FileEx.writeText(fn, str, charset);
	}

	public static double abs(double v) {
		return (v < 0) ? -v : v;
	}

	// 正值
	public static double positive(double v) {
		return abs(v);
	}

	// 负值
	public static double negative(double v) {
		return -abs(v);
	}

	// 负值
	public static double neg(double v) {
		return negative(v);
	}

	// 正/负
	public static double pon(double v, boolean p) {
		return p ? abs(v) : neg(v);
	}

	public static int abs(int v) {
		return (v < 0) ? -v : v;
	}

	// 正值
	public static int positive(int v) {
		return abs(v);
	}

	// 负值
	public static int negative(int v) {
		return -abs(v);
	}

	// 负值
	public static int neg(int v) {
		return negative(v);
	}

	// 正/负
	public static int pon(int v, boolean p) {
		return p ? abs(v) : neg(v);
	}

	public static long abs(long v) {
		return (v < 0) ? -v : v;
	}

	// 正值
	public static long positive(long v) {
		return abs(v);
	}

	// 负值
	public static long negative(long v) {
		return -abs(v);
	}

	// 负值
	public static long neg(long v) {
		return negative(v);
	}

	// 正/负
	public static long pon(long v, boolean p) {
		return p ? abs(v) : neg(v);
	}

	public static int createTmpId() {
		String uuid = UUID.randomUUID().toString();
		return Math.abs(uuid.hashCode());
	}

	public static int hashCode(final Object... keys) {
		return MultiKey2.calcHashCode(keys);
	}

	// [文件名|函数名|行号]
	public static String getFileLineMethod() {
		return getFileLineMethod(1);
	}

	// [文件名|函数名|行号]
	public static String getFileLineMethod(int statck) {
		StackTraceElement traceElement = ((new Exception()).getStackTrace())[statck];
		StringBuffer toStringBuffer = new StringBuffer("[")
				.append(traceElement.getFileName()).append(" | ")
				.append(traceElement.getLineNumber()).append(" | ")
				.append(traceElement.getMethodName()).append("]");
		return toStringBuffer.toString();
	}

	// 当前文件名
	public static String _FILE_() {
		return _FILE_(1);
	}

	// 当前方法名
	public static String _FUNC_() {
		return _FUNC_(1);
	}

	// 当前行号
	public static int _LINE_() {
		return _LINE_(1);
	}

	// 当前文件名
	public static String _FILE_(int stack) {
		StackTraceElement traceElement = ((new Exception()).getStackTrace())[stack];
		return traceElement.getFileName();
	}

	// 当前方法名
	public static String _FUNC_(int stack) {
		StackTraceElement traceElement = ((new Exception()).getStackTrace())[stack];
		return traceElement.getMethodName();
	}

	// 当前行号
	public static int _LINE_(int stack) {
		StackTraceElement traceElement = ((new Exception()).getStackTrace())[stack];
		return traceElement.getLineNumber();
	}

	public static final void println(Object... args) {
		print(args);
		System.out.println();
	}

	public static final double angle(int x1, int y1, int x2, int y2) {
		int x = Math.abs(x1 - x2);
		int y = Math.abs(y1 - y2);
		double z = Math.sqrt(x * x + y * y);
		return (Math.asin(y / z) / Math.PI * 180);// 最终角度
	}

	public static final void print(Object... args) {
		StringBuffer sb = StringBufPool.borrowObject();
		try {
			int length = args.length;
			int p = 0;
			for (Object o : args) {
				sb.append(o);
				p++;
				if (p < length)
					sb.append(", ");
			}
			System.out.print(sb);
		} finally {
			StringBufPool.returnObject(sb);
		}
	}

	// ///////////////////////////////////////////////////
	public static final <E> List<E> singletonEmptyList() {
		return ListEx.singletonEmptyList;
	}

	public static final <K, V> Map<K, V> singletonEmptyMap() {
		return MapEx.singletonEmptyMap;
	}

	public static final <E> Set<E> singletonEmptySet() {
		return NewSet.singletonEmptySet;
	}

	public static final <E> Set<E> newSet() {
		return Collections.synchronizedSet(new HashSet());
	}

	public static final <K, V> Map<K, V> newMap(int n) {
		return Collections.synchronizedMap(new HashMap(n));
	}

	public static final <K, V> Map<K, V> newMap() {
		return Collections.synchronizedMap(new HashMap());
	}

	public static final <K, V> TimeoutMap<K, V> newTimeoutMap(
			final ScheduledExecutorService executor, long requestMapPollTimeMillis) {
		return new ConcurrentTimeoutMap<K, V>(executor, requestMapPollTimeMillis);
	}

	public static final <E> List<E> newList(int n) {
		return Collections.synchronizedList(new Vector(n));
	}

	public static final <E> List<E> newList() {
		return Collections.synchronizedList(new ArrayList());
	}

	public static final <K, V> NewMap<K, V> newNewMap() {
		return new NewMap<K, V>();
	}

	public static final <K, V> Map<K, V> newConcurrentMap() {
		return new java.util.concurrent.ConcurrentHashMap<K, V>();
	}

	public static final <E> Set<E> newConcurrentSet() {
		return new com.bowlong.concurrent.ConcurrentSet<E>();
	}

	public static final <E> NewList<E> newNewList() {
		return new NewList<E>();
	}

	public static final <E> Queue<E> newQueue() {
		return new LinkedList<E>();
	}

	public static final <E> Queue<E> newConcurrentQueue() {
		return new java.util.concurrent.ConcurrentLinkedQueue<E>();
	}

	// //////////
	public static final <E> List<E> newCopyOnWriteList() {
		return new CopyOnWriteArrayList<E>();
	}

	public static final <T> Set<T> newSyncSet() {
		return Collections.synchronizedSet(new HashSet<T>());
	}

	public static final <K, V> Map<K, V> newSyncMap() {
		return Collections.synchronizedMap(new HashMap<K, V>());
	}

	public static final <T> List<T> newSyncList() {
		return Collections.synchronizedList(new ArrayList<T>());
	}

	public static final <E> Queue<E> newSyncQueue() {
		return new ConcurrentLinkedQueue<E>();
	}
	
	public static final <E> List<E> copyList(List l) {
		if (l == null)
			return null;
		List l2 = new Vector(l.size());
		l2.addAll(l);
		return l2;
	}

	public static final <E> List<E> toList(Map m) {
		List ret = newList();
		ret.addAll(m.values());
		return ret;
	}

	public static final List<Integer> toList(String s) {
		List<Integer> ret = newList();
		StringTokenizer st = new StringTokenizer(s, ",");
		while (st.hasMoreTokens()) {
			String str = st.nextToken();
			int e = NumEx.stringToInt(str.trim());
			if (e <= 0)
				continue;
			ret.add(e);
		}
		return ret;
	}

	public static final List<Integer> toList(int[] vars) {
		List ret = newList();
		for (int v : vars) {
			ret.add(v);
		}
		return ret;
	}

	public static final List<String> toList(String[] vars) {
		List ret = newList();
		for (String v : vars) {
			ret.add(v);
		}
		return ret;
	}

	public static final Map toMap(List l) {
		Map ret = newMap();
		int i = 1;
		for (Object o : l) {
			ret.put(i, o);
			i++;
		}
		return ret;
	}

	public static final Map toMap(String s) {
		Properties p = new Properties();
		try {
			StringReader sr = new StringReader(s);
			p.load(sr);
			return p;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return p;
	}

	public static boolean in(int[] zbx, int id) {
		for (int i : zbx) {
			if (id == i)
				return true;
		}
		return false;
	}

	// 是否存在交集
	public static final boolean isIntersected(List l1, List l2) {
		return Collections.disjoint(l1, l2);
	}

	// 求交集:小心参数1会被改变
	public static final List intersected(List l1, List l2) {
		l1.retainAll(l2);
		return l1;
	}

	// ///////////////////////////////////////////////////
	public static final ByteOutStream newStream() {
		return ByteOutPool.borrowObject();
	}

	public static final ByteInStream newStream(byte[] b) {
		return ByteInPool.borrowObject(b);
	}

	// ///////////////////////////////////////////////////
	// public static final Random random = new
	// Random(System.currentTimeMillis());
	public static final Random random = new Random(RndEx.randomNum());

	public static final boolean nextBool() {
		return random.nextBoolean();
	}

	public static final boolean nextBool(int max, int f) {
		int v = nextInt(max);
		return (v < f);
	}

	public static final <T> T rand(List objs) {
		int size = objs.size();
		if (size < 1)
			return null;
		else if (size == 1)
			return (T) objs.get(0);

		int v = random.nextInt(size);
		return (T) objs.get(v);
	}

	public static final int nextInt(int max) {
		if (max <= 0)
			return 0;
		return random.nextInt(max);
	}

	public static final int nextInt(int f, int t) {
		if (t <= f)
			return f;
		return random.nextInt(t - f) + f;
	}

	public static int min(int... n) {
		int min = 0;
		for (int i : n) {
			if (i <= 0)
				continue;
			if (min == 0) {
				min = i;
			} else {
				min = min < i ? min : i;
			}
		}
		return min;
	}

	public static String upper(String str) {
		return str.toUpperCase();
	}

	public static String lower(String str) {
		return str.toLowerCase();
	}

	public static String upperN1(String str) {
		return StrEx.upperN1(str);
	}

	public static String upperN(String str, int n) {
		return StrEx.upperN(str, n);
	}

	// 对List进行打乱顺序
	public static final List random(List list) {
		List ret = new Vector();
		int num = list.size();
		for (int n = num; n > 0; n--) {
			int p = random.nextInt(n);
			Object e = list.remove(p);
			ret.add(e);
		}
		return ret;
	}

	public static String pn(int n) {
		return n > 0 ? "+" + n : "" + n;
	}

	public static final List<Map> sort(List<Map> m1, final String key) {
		return ListEx.sort(m1, key);
	}

	// ///////////////////////////////////////////////////
	public static final byte[] zip(byte[] b) throws IOException {
		try (ByteOutStream baos = ByteOutPool.borrowObject();
				GZIPOutputStream gos = new GZIPOutputStream(baos);) {
			// gos.write(0xFF);
			// gos.write(0xFE);
			gos.write(b);
			gos.finish();
			return baos.toByteArray();
		}
	}

	public static final byte[] unzip(byte[] b) throws IOException {
		try (ByteOutStream baos = ByteOutPool.borrowObject();
				ByteInStream bais = newStream(b);
				GZIPInputStream gis = new GZIPInputStream(bais);) {
			byte[] buff = new byte[4 * 1024];
			int times = 1000;
			while (true) {
				if (times-- <= 0)
					break;

				int len = gis.read(buff);
				if (len <= 0)
					break;
				baos.write(buff, 0, len);
			}
			return baos.toByteArray();
		}
	}

	public static final byte[] unzip(byte[] b, int srcLen) throws IOException {
		try (InputStream bais = newStream(b);
				GZIPInputStream gis = new GZIPInputStream(bais);) {
			byte[] buff = new byte[srcLen];
			gis.read(buff);
			return buff;
		}
	}

	public static final byte[] serialization(final Object obj) throws Exception {
		if (obj == null)
			return new byte[0];
		try (ByteOutStream out = ByteOutPool.borrowObject();
				ObjectOutputStream oos = new ObjectOutputStream(out);) {
			oos.writeObject(obj);
			return out.toByteArray();
		} catch (Exception e) {
			throw e;
		}
	}

	public static final Object deserialization(final byte[] b) throws Exception {
		if (b == null || b.length <= 0)
			return null;
		try (ByteInStream in = ByteInPool.borrowObject(b);
				ObjectInputStream ois = new ObjectInputStream(in);) {
			return ois.readObject();
		} catch (Exception e) {
			throw e;
		}
	}

	public static final byte[] readStream(InputStream is) throws IOException {
		try (ByteOutStream out = ByteOutPool.borrowObject();) {
			byte[] buf = new byte[1024];
			int times = 1000;
			while (true) {
				if (times-- <= 0)
					break;

				try {
					int len = is.read(buf);
					if (len <= 0)
						break;
					out.write(buf, 0, len);
				} catch (Exception e) {
				}
			}
			byte[] b = out.toByteArray();
			return b;
		}
	}

	// ///////////////////////////////////////////////////
	public static final void close(final InputStream input) {
		if (input == null)
			return;
		try {
			input.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static final void close(final OutputStream output) {
		if (output == null)
			return;
		try {
			output.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// ///////////////////////////////////////////////////
	// 文件读写
	public static final byte[] readFully(File f) throws IOException {
		if (f == null || !f.exists())
			return null;
		int len = (int) f.length();
		byte[] b = new byte[len];
		try (FileInputStream fis = new FileInputStream(f);) {
			fis.read(b);
			return b;
		}
	}

	public static final void writeFully(File f, byte[] b) throws IOException {
		if (f == null)
			return;
		try (FileOutputStream fos = new FileOutputStream(f, false);) {
			fos.write(b);
			fos.close();
		}
	}

	public static final String readStream(InputStream is, String charset)
			throws Exception {
		byte[] b = readStream(is);
		return new String(b, charset);
	}

	public static final String readFully(File f, String charset)
			throws IOException {
		byte[] b = readFully(f);
		return new String(b, charset);
	}

	public static final byte[] readResource(String fn) throws IOException {
		URL url = Lib2.class.getResource(fn);
		String furl = url.getFile();
		File f = new File(furl);
		return readFully(f);
	}

	public static final void writeFully(File f, String v, String charset)
			throws IOException {
		byte[] b = v.getBytes(charset);
		writeFully(f, b);
	}

	// ///////////////////////////////////////////////////
	public static final String fmt_yyyy_MM_dd_HH_mm_ss_sss = "yyyy-MM-dd HH:mm:ss.SSS";
	public static final String fmt_yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";
	public static final String fmt_yyyy_MM_dd = "yyyy-MM-dd";
	public static final String fmt_HH_mm_ss = "HH:mm:ss";
	public static final String fmt_HH_mm = "HH:mm";
	public static final String fmt_MM_dd_HH_mm = "MM-dd HH:mm";
	public static final String fmtYyyyMm = "yyyyMM";
	public static final String fmtYyyyMmDd = "yyyyMMdd";
	public static final String fmt_yyyy_MM_dd_HH_mm = "yyyy-MM-dd HH:mm";
	public static final String fmt_yyyy_MM_dd_HH = "yyyy-MM-dd HH";
	public static final String fmt_MM_dd = "MM-dd";
	public static final String fmtMMddHHmmss = "MMddHHmmss";
	public static final String fmtYyyy = "yyyy";

	// public static final SimpleDateFormat sdf_yyyy_MM_dd_HH_mm_ss_sss = new
	// SimpleDateFormat(fmt_yyyy_MM_dd_HH_mm_ss_sss);
	// public static final SimpleDateFormat sdf_yyyy_MM_dd_HH_mm_ss = new
	// SimpleDateFormat(fmt_yyyy_MM_dd_HH_mm_ss);
	// public static final SimpleDateFormat sdf_yyyy_MM_dd = new
	// SimpleDateFormat(fmt_yyyy_MM_dd);
	// public static final SimpleDateFormat sdf_HH_mm = new
	// SimpleDateFormat(fmt_HH_mm);
	// public static final SimpleDateFormat sdf_HH_mm_ss = new
	// SimpleDateFormat(fmt_HH_mm_ss);
	// public static final SimpleDateFormat sdf_MM_dd_HH_mm = new
	// SimpleDateFormat(fmt_MM_dd_HH_mm);
	// public static final SimpleDateFormat sdfYyyyMmDd = new
	// SimpleDateFormat(fmtYyyyMmDd);
	// public static final SimpleDateFormat sdfYyyyMm = new
	// SimpleDateFormat(fmtYyyyMm);

	// 今天凌晨(0点0分)
	public static final long beginningToday() {
		try {
			Date d = beginningToday2();
			return d.getTime();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return 0;
	}

	public static final Date beginningToday2() {
		try {
			String s = beginningToday3();
			Date d = new SimpleDateFormat(fmt_yyyy_MM_dd).parse(s);
			return d;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return new Date();
	}

	public static final String beginningToday3() {
		try {
			return new SimpleDateFormat(fmt_yyyy_MM_dd).format(new Date());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	public static final long beginningTomorrow() {
		try {
			return beginningToday() + DateEx.TIME_DAY;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return 0;
	}

	public static final Date beginningTomorrow2() {
		try {
			long tm = beginningTomorrow();
			Date d = new Date(tm);
			return d;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return new Date();
	}

	public static final String beginningTomorrow3() {
		try {
			Date d = beginningTomorrow2();
			String s = new SimpleDateFormat(fmt_yyyy_MM_dd).format(d);
			return s;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	public static final long now() {
		return System.currentTimeMillis();
	}

	public static final Date date() {
		return new Date();
	}

	public static final String yearMMdd() {
		return new SimpleDateFormat(fmt_yyyy_MM_dd).format(new Date());
	}

	public static final String yearMMddHHmmss() {
		return new SimpleDateFormat(fmt_yyyy_MM_dd_HH_mm_ss).format(new Date());
	}

	public static final String hourMm() {
		return new SimpleDateFormat(fmt_HH_mm).format(new Date());
	}

	public static final String monthDdHHmm() {
		return new SimpleDateFormat(fmt_MM_dd_HH_mm).format(new Date());
	}

	// 两个时间的时间差
	public static final long timeDifference(Date d1, Date d2) {
		long l1 = d1.getTime();
		long l2 = d2.getTime();
		return l2 - l1;
	}

	// 延迟时间
	public static final Date delay(Date d, long delay) {
		return new Date(d.getTime() + delay);
	}

	// 当前时间之后某个时间
	public static final Date delay(long delay) {
		return new Date(now() + delay);
	}

	// 现在位于时间段内
	public static boolean isBetween(Date kssj, Date jssj) {
		Date now = new Date();
		if (now.before(kssj))
			return false;
		if (now.after(jssj))
			return false;
		return true;
	}

	// 过去
	public static boolean isPast(Date d) {
		Date now = new Date();
		return d.before(now);
	}

	// 未来
	public static boolean isFuture(Date d) {
		Date now = new Date();
		return d.after(now);
	}

	public static final String s(String s, Object... args) {
		return String.format(s, args);
	}

	public static final void s(StringBuffer sb, String s, Object... args) {
		String s2 = String.format(s, args);
		sb.append(s2);
	}

	public static final String sn(String s, Object... args) {
		return String.format(s + "\r\n", args);
	}

	public static final void sn(StringBuffer sb, String s, Object... args) {
		String s2 = String.format(s + "\r\n", args);
		sb.append(s2);
	}

	public static final String fmt(String s, Object... args) {
		return String.format(s, args);
	}

	public static final String format(String s, Object... args) {
		return String.format(s, args);
	}

	// 带1位小数
	public static final String n2s(int i) {
		if (i < 1000)
			return i + "";
		if (i < 1000 * 10)
			return String.format("%.1fK", ((double) i / 1000));
		if (i < 1000 * 1000)
			return String.format("%.1fW", ((double) i / 10000));
		if (i < 1000 * 1000 * 1000)
			return String.format("%.1fM", ((double) i / (1000 * 1000)));
		return String.format("%.1fG", ((double) i / (1000 * 1000 * 1000)));
	}

	// 自动识别是否带小数
	public static final String n2sn(long i) {
		if (i < 1000)
			return i + "";
		if (i < 1000 * 10)
			return String.format("%.1fK", ((double) i / 1000));
		if (i < 1000 * 1000)
			return String.format("%.0fW", ((double) i / 10000));
		if (i < 1000 * 1000 * 1000)
			return String.format("%.0fM", ((double) i / (1000 * 1000)));
		return String.format("%.1fG", ((double) i / (1000 * 1000 * 1000)));
	}

	// 带小数,支持负数
	public static final String n(int i) {
		boolean abs = false;
		if (i < 0) {
			i = -i;
			abs = true;
		}
		String s = n2s(i);
		String r = abs ? ('-' + s) : s;
		return r;
	}

	// ///////////////////////////////////////////////////
	// 计算两点间距离
	public final static int distance(int x1, int y1, int x2, int y2) {
		double v = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
		return (int) v;
	}

	// 计算百分率
	public static final int percent(double v, double max) {
		if (v <= 0 || max <= 0)
			return 0;
		int r = (int) (v * 100 / max);
		return r > 100 ? 100 : r;
	}

	// ///////////////////////////////////////////////////
	public static final int argb(Color c) {
		return argb(c.getAlpha(), c.getRed(), c.getGreen(), c.getBlue());
	}

	public static final int argb(int a, int r, int g, int b) {
		return (r << 24) + (r << 16) + (g << 8) + b;
	}

	public static final int[] argb(long argb) {
		int a = (byte) ((argb >> 24) & 0xff);
		int r = (byte) ((argb >> 16) & 0xff);
		int g = (byte) ((argb >> 8) & 0xff);
		int b = (byte) ((argb >> 0) & 0xff);
		int[] v = { a, r, g, b };
		return v;
	}

	// ///////////////////////////////////////////////////
	public static final int rgb(Color c) {
		return rgb(c.getAlpha(), c.getRed(), c.getGreen(), c.getBlue());
	}

	public static final int rgb(int a, int r, int g, int b) {
		return (r << 16) + (g << 8) + b;
	}

	public static final int[] rgb(int rgb) {
		int r = (byte) ((rgb >> 16) & 0xff);
		int g = (byte) ((rgb >> 8) & 0xff);
		int b = (byte) ((rgb >> 0) & 0xff);
		int[] v = { r, g, b };
		return v;
	}

	// ///////////////////////////////////////////////////
	public static final boolean isNull(Object o) {
		return o == null;
	}

	public static final boolean isEmpty(byte[] o) {
		return o == null || o.length <= 0;
	}

	public static final boolean isEmpty(List o) {
		return o == null || o.isEmpty();
	}

	public static final boolean isEmpty(Map o) {
		return o == null || o.isEmpty();
	}

	public static final boolean isEmpty(String o) {
		return o == null || o.isEmpty();
	}

	public static final boolean isInt(String s) {
		try {
			Integer.parseInt(s);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	// 错误堆栈的内容
	public static final String e2s(Exception e) {
		StringBuffer sb = StringBufPool.borrowObject();
		try {
			sb.append(e);
			sb.append("\r\n");
			for (StackTraceElement ste : e.getStackTrace()) {
				sb.append("at ");
				sb.append(ste);
				sb.append("\r\n");
			}
			return sb.toString();
		} finally {
			StringBufPool.returnObject(sb);
		}
	}

	// ///////////////////////////////////////////////////

	// public static Executor singleThreadExecutor = null;
	// public static Executor fixed4ThreadPool = null;
	// public static ScheduledExecutorService scheduled4Pool = null;
	//
	// public static final void executeSingle(Runnable r) {
	// if (singleThreadExecutor == null)
	// singleThreadExecutor = ThreadEx.newSingleThreadExecutor();
	// singleThreadExecutor.execute(r);
	// }
	//
	// public static final void execute4Fixed(Runnable r) {
	// if (fixed4ThreadPool == null)
	// fixed4ThreadPool = ThreadEx.newFixedThreadPool(4);
	// fixed4ThreadPool.execute(r);
	// }
	//
	// // 延时执行
	// public static final ScheduledFuture<?> scheduled4(Runnable r, long delay)
	// {
	// if (scheduled4Pool == null)
	// scheduled4Pool = ThreadEx.newScheduledPool(4);
	// return scheduled4Pool.schedule(r, delay, TimeUnit.MILLISECONDS);
	// }
	//
	// // 定间隔时间执行
	// public static final ScheduledFuture<?> scheduled4FixedDelay(Runnable r,
	// long initialDelay, long delay) {
	// if (scheduled4Pool == null)
	// scheduled4Pool = ThreadEx.newScheduledPool(4);
	//
	// return scheduled4Pool.scheduleWithFixedDelay(r, initialDelay, delay,
	// TimeUnit.MILLISECONDS);
	// }
	//
	// // 确定时分秒，每日执行
	// public static final ScheduledFuture<?> scheduled4EveryDay(Runnable r,
	// int hour, int minute, int sec) {
	// long now = now();
	// long tomorrow = beginningTomorrow();
	// long h = DateEx.hour();
	// long m = DateEx.minute();
	// long s = DateEx.second();
	// long initialDelay = 0;
	// long e1 = h * DateEx.TIME_HOUR + m * DateEx.TIME_MINUTE + s
	// * DateEx.TIME_SECOND;
	// long e2 = hour * DateEx.TIME_HOUR + minute * DateEx.TIME_MINUTE + sec
	// * DateEx.TIME_SECOND;
	// if (e1 < e2) {
	// initialDelay = e2 - e1;
	// } else {
	// initialDelay = tomorrow - now + e2;
	// }
	// long delay = DateEx.TIME_DAY;
	// return scheduled4FixedRate(r, initialDelay, delay);
	// }
	//
	// // 定时执行
	// public static final ScheduledFuture<?> scheduled4FixedRate(Runnable r,
	// long initialDelay, long delay) {
	// if (scheduled4Pool == null)
	// scheduled4Pool = ThreadEx.newScheduledPool(4);
	//
	// return scheduled4Pool.scheduleAtFixedRate(r, initialDelay, delay,
	// TimeUnit.MILLISECONDS);
	// }

	public static final boolean isTimeout(long LASTTIME, long TIMEOUT) {
		if (TIMEOUT <= 0)
			return false;
		long l2 = System.currentTimeMillis();
		long t = l2 - LASTTIME;
		return (t > TIMEOUT);
	}

	public static final boolean isTimeout(Date DLASTTIME, long TIMEOUT) {
		if (TIMEOUT <= 0)
			return false;
		long LASTTIME = DLASTTIME.getTime();
		return isTimeout(LASTTIME, TIMEOUT);
	}

	public static final String getAppRoot() {
		return System.getProperty("user.dir");
	}

	public static final Map getMap(Map map, Object key) {
		return MapEx.getMap(map, key);
	}

	public static final List getList(Map map, Object key) {
		return MapEx.getList(map, key);
	}

	public static final String getString(Map map, String key) {
		return MapEx.getString(map, key);
	}

	public static final boolean getBool(Map map, String key) {
		return MapEx.getBoolean(map, key);
	}

	public static final int getInt(Map map, String key) {
		return MapEx.getInt(map, key);
	}

	public static final double getDouble(Map map, String key) {
		return MapEx.getDouble(map, key);
	}

	public static final String getShortPinYin(String s) {
		return PinYin.getShortPinYin(s);
	}

	public static final String upperFirst(String s) {
		return StrEx.upperFirst(s);
	}

	public static final int compareTo(Object v1, Object v2) {

		if (v1 == null || v2 == null)
			return 0;

		if (v1 instanceof Byte && v2 instanceof Byte) {
			Boolean i1 = (Boolean) v1;
			Boolean i2 = (Boolean) v2;
			return i1.compareTo(i2);
		} else if (v1 instanceof Byte && v2 instanceof Byte) {
			Byte i1 = (Byte) v1;
			Byte i2 = (Byte) v2;
			return i1.compareTo(i2);
		} else if (v1 instanceof Short && v2 instanceof Short) {
			Short i1 = (Short) v1;
			Short i2 = (Short) v2;
			return i1.compareTo(i2);
		} else if (v1 instanceof Integer && v2 instanceof Integer) {
			Integer i1 = (Integer) v1;
			Integer i2 = (Integer) v2;
			return i1.compareTo(i2);
		} else if (v1 instanceof Long && v2 instanceof Long) {
			Long i1 = (Long) v1;
			Long i2 = (Long) v2;
			return i1.compareTo(i2);
		} else if (v1 instanceof java.math.BigInteger
				&& v2 instanceof java.math.BigInteger) {
			java.math.BigInteger i1 = (java.math.BigInteger) v1;
			java.math.BigInteger i2 = (java.math.BigInteger) v2;
			return i1.compareTo(i2);
		} else if (v1 instanceof java.math.BigDecimal
				&& v2 instanceof java.math.BigDecimal) {
			java.math.BigDecimal i1 = (java.math.BigDecimal) v1;
			java.math.BigDecimal i2 = (java.math.BigDecimal) v2;
			return i1.compareTo(i2);
		} else if (v1 instanceof Float && v2 instanceof Float) {
			Float i1 = (Float) v1;
			Float i2 = (Float) v2;
			return i1.compareTo(i2);
		} else if (v1 instanceof Double && v2 instanceof Double) {
			Double i1 = (Double) v1;
			Double i2 = (Double) v2;
			return i1.compareTo(i2);
		} else if (v1 instanceof Date && v2 instanceof Date) {
			Date i1 = (Date) v1;
			Date i2 = (Date) v2;
			return i1.compareTo(i2);
		} else if (v1 instanceof java.sql.Date && v2 instanceof java.sql.Date) {
			java.sql.Date i1 = (java.sql.Date) v1;
			java.sql.Date i2 = (java.sql.Date) v2;
			return i1.compareTo(i2);
		} else if (v1 instanceof java.sql.Timestamp
				&& v2 instanceof java.sql.Timestamp) {
			java.sql.Timestamp i1 = (java.sql.Timestamp) v1;
			java.sql.Timestamp i2 = (java.sql.Timestamp) v2;
			return i1.compareTo(i2);
		} else if (v1 instanceof java.sql.Time && v2 instanceof java.sql.Time) {
			java.sql.Time i1 = (java.sql.Time) v1;
			java.sql.Time i2 = (java.sql.Time) v2;
			return i1.compareTo(i2);
		} else if (v1 instanceof String && v2 instanceof String) {
			String i1 = (String) v1;
			String i2 = (String) v2;
			return i1.compareTo(i2);
		} else if (v1 instanceof java.lang.Enum && v2 instanceof java.lang.Enum) {
			java.lang.Enum i1 = (java.lang.Enum) v1;
			java.lang.Enum i2 = (java.lang.Enum) v2;
			return i1.compareTo(i2);
		}
		return -1;
	}

	public static long getTimeLong(int d, int h, int m) {
		long time = 0l;
		time += d * DateEx.TIME_DAY;
		time += h * DateEx.TIME_HOUR;
		time += m * DateEx.TIME_MINUTE;
		return time;
	}

	public static boolean eq(Object v1, Object v2) {
		return compareTo(v1, v2) == 0;
	}

	public static Map parseMap(String json) {
		Map map = (Map) JSON.parse(json);
		return map;
	}

	public static List parseList(String json) {
		List list = (List) JSON.parse(json);
		return list;
	}

	public static String toJSONString(Map map) {
		return JSON.toJSONString(map);
	}

	public static String toJSONString(List list) {
		return JSON.toJSONString(list);
	}

	public static String toJSONString(String json) {
		Object object = JSON.parse(json);
		return JSON.toJSONString(object);
	}

	public static File class2File(Class<?> class1) {
		boolean src = FileEx.exists("src");
		String pkg = class1.getPackage().getName();
		String path = pkg.replaceAll("\\.", "/");
		String fn = (src ? "src/" : "") + path + "/" + class1.getSimpleName()
				+ ".java";
		return new File(fn);
	}

	public static String readText(File fn) throws IOException {
		return FileEx.readText(fn);
	}

	public static void writeText(File fn, String str, Charset charset) {
		FileEx.writeText(fn, str, charset);
	}
}
